package com.cooper.scraper;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.content.res.Resources.NotFoundException;
import android.util.Log;

public class Exp {

	private Scraper scraper;

	Exp(Scraper scraper, String rule, boolean repeat) {
		this.rule = rule;
		this.repeat = repeat;
		this.scraper = scraper;
	}

	public Exp(Scraper scraper, XmlPullParser xml) {
		this.scraper = scraper;
		repeat = Scraper
				.parseBool(xml.getAttributeValue(null, "repeat"), false);
		String nocleanStr = xml.getAttributeValue(null, "noclean");
		if (nocleanStr != null && !nocleanStr.trim().equals("")) {
			for (String s : nocleanStr.split(",")) {
				noclean.add(Integer.parseInt(s));
			}
		}

		String trimStr = xml.getAttributeValue(null, "trim");
		if (trimStr != null && !trimStr.trim().equals("")) {
			for (String s : trimStr.split(",")) {
				trim.add(Integer.parseInt(s));
			}
		}

		clear = Scraper.parseBool(xml.getAttributeValue(null, "clear"), false);
	}

	public boolean clear = false;
	private boolean repeat = false;
	private List<Integer> noclean = new ArrayList<Integer>();
	private List<Integer> trim = new ArrayList<Integer>();
	private String rule;

	public String getRule() {
		return rule;
	}

	public void setRule(String rule) {
		this.rule = rule;
	}

	public String matchExp(String useRule, String input, String output)
			throws XmlPullParserException, IOException {
		String result = "";
		List<String> rules = new ArrayList<String>();
		if ((useRule == null) || useRule.trim().equals("")) {
			rules.add(input);
			result = replaceOutput(rules, output);
		} else {
			Pattern p = Pattern.compile(useRule);
			Matcher m = p.matcher(input);
			List<String> regGroups = new ArrayList<String>();
			boolean found = false;
			while (m.find()) {
				found = true;
				regGroups.clear();
				for (int i = 1; i <= m.groupCount(); i++) {
					regGroups.add(m.group(i) == null ? "" : m.group(i));
				}
				result += replaceOutput(regGroups, output);

				if (!repeat)
					break;
			}
			if (!found) {
				return null;
			}
		}
		return result;
	}

	private String unicode2GBK(String data) {
		char letter = (char) Integer.parseInt(data, 16);
		return String.valueOf(letter);
	}

	String clean(String str) {
		// clean Unicode2GBK
		Matcher m = Pattern.compile("\\\\u(\\w{4})").matcher(str);
		StringBuffer result = new StringBuffer();
		while (m.find()) {
			m.appendReplacement(result, unicode2GBK(m.group(1)));
		}
		m.appendTail(result);

		return result.toString().replaceAll("</{0,1}.*?>", "")
				.replaceAll("&.*?;", "").replace("\\/", "/")
				.replace("&", "&amp;").replace("<", "&lt;")
				.replace(">", "&gt;").replace("'", "&apos;")
				.replace("\"", "&quot;").replace("&nbsp", " ");
	}

	private String replaceOutput(List<String> expGroupResults, String output)
			throws XmlPullParserException, IOException {
		String result = output;

		for (int i = expGroupResults.size() - 1; i >= 0; i--) {
			String egResults = expGroupResults.get(i);
			egResults = egResults == null ? "" : egResults;

			if (!noclean.contains(Integer.valueOf(i + 1))) {
				egResults = clean(egResults);
			}
			if (trim.contains(Integer.valueOf(i + 1))) {
				egResults = egResults.trim();
			}
			result = result.replace("\\" + String.valueOf(i + 1), egResults);
		}
		result = matchSubFuncTag(result);
		return result;
	}

	private String matchSubFuncTag(String outResult)
			throws XmlPullParserException, IOException {
		String subUrlResult = matchSubUrlTag(outResult);
		String subDataResult = matchSubDataTag(subUrlResult);
		return subDataResult;
	}

	private String matchSubUrlTag(String outResult)
			throws XmlPullParserException, IOException {
		Pattern p = Pattern
				.compile("<url[^>]*?function=\"(\\w+)\"[^>]*>([^<]*)</url>");
		Matcher m = p.matcher(outResult);
		StringBuffer result = new StringBuffer();
		while (m.find()) {
			//Log.d("RegExp", "found function url:" + outResult);
			m.appendReplacement(result,
					matchSubFuncTag(ResultUrl.urlFactory(m.group(), null)
							.get(0)));
		}
		m.appendTail(result);

		return result.toString();
	}

	private String matchSubDataTag(String outResult)
			throws XmlPullParserException, IOException {
		Pattern p = Pattern
				.compile("<sub[^>]*?function=\"(\\w+)\"[^>]*>((\\s|\\S)*?)</sub>");
		Matcher m = p.matcher(outResult);
		StringBuffer result = new StringBuffer();
		while (m.find()) {
			//Log.d("RegExp", "found data function url:" + outResult);
			m.appendReplacement(result, matchSubFuncTag(m.group(1), m.group(2)));
		}
		m.appendTail(result);

		return result.toString();
	}

	private String matchSubFuncTag(String function, String data)
			throws NotFoundException, XmlPullParserException, IOException {
		Scraper subFuncScraper = scraper.clonScraper();
		subFuncScraper.setBufferValue(1, data);
		return subFuncScraper.getDefineTag(function).matchRegExp();
	}

	private String matchSubFuncTag(ResultUrl url) throws NotFoundException,
			XmlPullParserException, IOException {
		Scraper subFuncScraper = scraper.clonScraper();
		if (url.getUrl() != null && !"".equals(url.getUrl().trim()))
			try {
				subFuncScraper.setBufferValue(1, HttpDownload.getInstance()
						.downloadPage(url.getUrl(), url.getEncodingType()));
			} catch (DownloadException e) {
				subFuncScraper.setBufferValue(1, "");
			}
		return subFuncScraper.getDefineTag(url.getFunction()).matchRegExp();
	}
}